package ioStream;

import org.junit.Test;

import java.io.*;

/**
 * @author 杜伟毅
 * @version 1.0
 * @since 2024/09/19
 * IO流练习
 */
public class IoStreamTest {
    //输入流--------------------------
    @Test
    public void testRead1() throws IOException, InterruptedException {//节点流
        File file = new File("C:\\Users\\白草风归\\Music\\ceshi\\a.txt");
        //将管子（FileInputStream）插到文件上（file）
        InputStream inputStream = new FileInputStream(file);

        int read;
        int i = 0;
        byte[] bytes = new byte[10];
        while ((read = inputStream.read()) != -1) {
//            System.out.println(read);
            byte b = (byte) read;
            bytes[i] = b;
            i++;
        }
        System.out.println(new String(bytes));
    }

    @Test
    public void testRead2() throws IOException, InterruptedException {//节点流
        File file = new File("C:\\Users\\白草风归\\Music\\ceshi\\a.txt");
        //将管子（FileInputStream）插到文件上（file）
        InputStream inputStream = new FileInputStream(file);

        int len;
        byte[] bytes = new byte[2];
        StringBuilder sb = new StringBuilder();
        //如果每次读，就会得出读出来的字节，(len=inputStream.read()),如果读得是一个数组，则读出来的是数组的长度（数组里有多少个数）,把后面空的舍弃掉(len=inputStream.read(bytes))
        while ((len = inputStream.read(bytes)) != -1) {
            //每次读出多少字节，就把对应的字节转化成字符串
            String s = new String(bytes, 0, len);
            sb.append(s);
        }
        System.out.println(sb);
    }

    //输入流--------------------------
    @Test
    public void writeTest() throws IOException {
        File file = new File("C:\\Users\\白草风归\\Music\\ceshi\\a.txt");
        byte[] bytes = {97, 98, 99, 100};
        //true代表追加，不写则会覆盖掉之前的内容
        OutputStream fileOutputStream = new FileOutputStream(file, true);
        for (int i = 0; i < bytes.length; i++) {
            fileOutputStream.write(bytes[i]);
        }
        fileOutputStream.write("afafdsaf".getBytes());
    }

    //一个一个字节读写（仅作测试用，一般不用，太慢）
    @Test
    public void copeFileTest() throws IOException {
        //把输入流建立在文件上
        File readFile = new File("D:\\java测试\\测试123.mp4");
        FileInputStream fileInputStream = new FileInputStream(readFile);

        //建立一个输出流
        File writeFile = new File("D:\\java测试\\voide\\测试123.mp4");
        FileOutputStream fileOutputStream = new FileOutputStream(writeFile);

        //一边读流中的字节，一边写出到文件
        int b = 0;
        while ((fileInputStream.read()) != -1) {
            fileOutputStream.write(b);
        }
    }

    //一个一个数组读写
    @Test
    public void copeFileTest2() throws IOException {
        //把输入流建立在文件上
        File readFile = new File("D:\\1java测试\\测试123.mp4");
        FileInputStream fileInputStream = new FileInputStream(readFile);

        //建立一个输出流
        File writeFile = new File("D:\\1java测试\\voide\\测试123.mp4");
        FileOutputStream fileOutputStream = new FileOutputStream(writeFile);

        //建立缓冲区
        byte[] bytes = new byte[1024 * 1024 * 5];//=5M
        int len = 0;
        while ((len = fileInputStream.read(bytes)) != -1) {
            fileOutputStream.write(bytes, 0, len);
        }
    }

    //一个一个数组读写(优化版)
    @Test
    public void copeFileTest3() {
        FileInputStream fileInputStream = null;
        FileOutputStream fileOutputStream = null;
        try {
            //把输入流建立在文件上
            File readFile = new File("D:\\1java测试\\测试123.mp4");
            fileInputStream = new FileInputStream(readFile);

            //建立一个输出流
            File writeFile = new File("D:\\1java测试\\voide\\测试123.mp4");
            fileOutputStream = new FileOutputStream(writeFile);

            //建立缓冲区
            byte[] bytes = new byte[1024 * 1024 * 5];//=5M
            int len = 0;
            while ((len = fileInputStream.read(bytes)) != -1) {
                fileOutputStream.write(bytes, 0, len);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //释放资源，关闭流

            //为何要加if？因为如果fileInputStream以及fileOutputStream在上面并未创建，而下面的代码又在关闭，这样不合适，会报错
            if (fileInputStream != null) {
                try {
                    fileInputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (fileOutputStream != null) {
                try {
                    fileOutputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    //一个一个数组读写(最终优化版,自动关闭资源)
    @Test
    public void copeFileTest4() {
        //将定义资源放在try里
        try (FileInputStream fileInputStream = new FileInputStream("D:\\1java测试\\测试123.mp4");
             FileOutputStream fileOutputStream = new FileOutputStream("D:\\1java测试\\voide\\测试123.mp4")
        ) {
            //建立缓冲区
            byte[] bytes = new byte[1024 * 1024 * 5];//=5M
            int len = 0;
            while ((len = fileInputStream.read(bytes)) != -1) {
                fileOutputStream.write(bytes, 0, len);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * @author 杜伟毅
     * @since 2024/9/20 0020 23:25
     * 字符流
     */
    @Test
    public void readerTest() throws IOException {
        //把输入流建立在文件上
        File readFile = new File("D:\\1java测试\\a.txt");
        Reader reader = new FileReader(readFile);

        //建立一个输出流
        File writeFile = new File("D:\\1java测试\\voide\\a.txt");
        Writer writer = new FileWriter(writeFile);

        //一边读流中的字节，一边写出到文件
        int b;
        while ((b = reader.read()) != -1) {
            writer.write(b);
        }

        reader.close();//在调用close方法的时候会默认调用flush(刷新)，如果即不调用close方法，也不调用flush方法，则会导致数据流不过指定位置
        writer.close();
    }

    /**
     * @author 杜伟毅
     * @since 2024/9/20 0020 23:47
     * 增加处理流写法（可以一行一行打印）
     */
    @Test
    public void bufferedReaderTest1() throws IOException {
        //把输入流建立在文件上
        File readFile = new File("D:\\1java测试\\a.txt");
        Reader reader = new FileReader(readFile);

        //建立一个输出流
        File writeFile = new File("D:\\1java测试\\voide\\a.txt");
        Writer writer = new FileWriter(writeFile);

        //处理流
        BufferedReader bufferedReader = new BufferedReader(reader);
        //一边读流中的字节，一边写出到文件
        String content;
        while ((content = bufferedReader.readLine()) != null) {
            System.out.println(content);
        }

        reader.close();//在调用close方法的时候会默认调用flush(刷新)，如果即不调用close方法，也不调用flush方法，则会导致数据流不过指定位置
        writer.close();
        bufferedReader.close();
    }

    /**
     * 将对象写到磁盘上(序列化)
     * @author 杜伟毅
     * @since 2024/9/21 0021 19:34
     */
    @Test
    public void setTest() throws IOException {
        OutputStream outputStream = new FileOutputStream("D:\\1java测试\\a.txt");
        ObjectOutputStream objectOutputStream = new ObjectOutputStream(outputStream);
        //写一个对象到磁盘
        objectOutputStream.writeObject(new User(12));

        objectOutputStream.close();
        outputStream.close();
    }

    /**
     * 从磁盘上找出对象(反序列化)
     * @author 杜伟毅
     * @since 2024/9/21 0021 19:34
     */
    @Test
    public void getTest() throws IOException, ClassNotFoundException {
        InputStream inputStream = new FileInputStream("D:\\1java测试\\a.txt");
        ObjectInputStream objectInputStream = new ObjectInputStream(inputStream);
        //写一个对象到磁盘
        User user = (User) objectInputStream.readObject();
        System.out.println(user);
        objectInputStream.close();
        inputStream.close();
    }

    /**
     * 从磁盘上找出对象(反序列化)
     * @author 杜伟毅
     * @since 2024/9/21 0021 19:34
     */
    @Test
    public void deepCopyTest() throws IOException, ClassNotFoundException {

    }
}
